﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using umbraco.IO;
using System.Web.Compilation;
using umbraco.controls.Tree;
using System.Web.UI.WebControls;
using ClientDependency.Core.Controls;
using System.Web.Script.Serialization;
using System.Xml.Linq;
using System.Web.UI.HtmlControls;
using System.Xml;
using umbraco.cms.presentation.Trees;
using System.IO;
using System.Web;
using DigibizTree.Shared;
using umbraco;
using System.Collections.Specialized;
using DigibizTree.Shared.Tree;
using ClientDependency.Core;
using umbraco.controls.Images;

namespace DigibizTree.Picker
{

    /// <summary>
    /// The user interface to display to the content editor.
    /// </summary>
    [ClientDependency(ClientDependencyType.Javascript, "ui/jqueryui.js", "UmbracoClient")]
    public class DigibizPickerView: Control, INamingContainer
    {

        #region Static Constructor
        
        /// <summary>
        /// This adds our filtered media tree definition to the TreeDefinitionCollection at runtime
        /// instead of having to declare it in the database.
        /// </summary>
        static DigibizPickerView()
        {
            if (TreeDefinitionCollection.Instance
                        .Where(x => x.TreeType == typeof(DigibizMediaTree))
                        .Count() == 0)
            {
                lock (m_Locker)
                {

                    if (TreeDefinitionCollection.Instance
                            .Where(x => x.TreeType == typeof(DigibizMediaTree))
                            .Count() == 0)
                    {
                        //Find the media tree to duplicate.
                        var mediaTree = TreeDefinitionCollection.Instance.Where(x => x.Tree.Alias == "media").Single();
                        var filteredMediaTree = new TreeDefinition(typeof(DigibizMediaTree),
                            new umbraco.BusinessLogic.ApplicationTree(true, false, 0,
                                mediaTree.Tree.ApplicationAlias,
                                "DigibizMediaTree",
                                mediaTree.Tree.Title,
                                mediaTree.Tree.IconClosed,
                                mediaTree.Tree.IconOpened,
                                "mediaTree",
                                "Picker.DigibizMediaTree",
                                mediaTree.Tree.Action),
                            mediaTree.App);

                        //Add it to the collection at runtime.
                        TreeDefinitionCollection.Instance.Add(filteredMediaTree);
                    }
                }
            }
        } 

        #endregion

        /// <summary>
        /// Constructor sets default properties.
        /// </summary>
        public DigibizPickerView()
        {
            StartNodeId = -1;
        }

        #region Static members

        /// <summary>
        /// Used for locking code blocks.
        /// </summary>
        private static readonly object m_Locker = new object();

        #endregion

        #region Protected members

        protected DigibizTreeControl TreePickerControl;
        public HiddenField PickedValue;
        protected HtmlGenericControl MessageColumn;
        protected HtmlGenericControl CenterColumn;
        protected HtmlGenericControl PreviewColumn;
        protected HtmlGenericControl RightColumn;
        protected HtmlGenericControl CreateColumn;
        protected TextBox SearchTextBox;
        protected Button SearchButton;

        #endregion

        #region public Properties

        /// <summary>
        /// The start node id
        /// </summary>
        public int StartNodeId { get; set; }

        /// <summary>
        /// Determines what extensions are allowed
        /// </summary>
        public string AllowedExtensions { get; set; }

        /// <summary>
        /// Determines what media types are allowed
        /// </summary>
        public string AllowedMediaTypes { get; set; }

        /// <summary>
        /// Determines if this is the tree for the create popup.
        /// </summary>
        public bool IsCreateTree { get; set; }

        /// <summary>
        /// Determines if the start node can be selected
        /// </summary>
        public bool SelectStartNode { get; set; }

        /// <summary>
        /// Determines if multiple media items can be selected.
        /// </summary>
        public bool SelectMultipleNodes { get; set; }

        /// <summary>
        /// The class on the top div.
        /// </summary>
        public string PickerClass { get; set; }

        /// <summary>
        /// The property alias to check for crops
        /// </summary>
        public string CropPropertyAlias { get; set; }

        /// <summary>
        /// The name of the defined crop to look for
        /// </summary>
        public string CropName { get; set; }

        /// <summary>
        /// Enables the search
        /// </summary>
        public bool SearchEnabled { get; set; }

        /// <summary>
        /// Enables the autosuggest when searching media
        /// </summary>
        public bool AutoSuggestEnabled { get; set; }

        /// <summary>
        /// Sets the search method - either under start node or selected node
        /// </summary>
        public string SearchMethod { get; set; }

        #endregion

        /// <summary>
        /// Initialize the control, make sure children are created.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            EnsureChildControls();
        }

        /// <summary>
        /// Add the resources (sytles/scripts).
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            //Add the js/css required.
            this.AddAllDAMPClientDependencies();

            TreePickerControl.TreeType = "DigibizMediaTree";
            TreePickerControl.App = "media";
        }

        /// <summary>
        /// Creates the child controls for this control.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            EnsureChildControls();

            //Create the tree control.
            TreePickerControl = new DigibizTreeControl();
            TreePickerControl.ID = "TreePicker";
            TreePickerControl.IsDialog = true;
            TreePickerControl.ShowContextMenu = false;
            TreePickerControl.DialogMode = umbraco.cms.presentation.Trees.TreeDialogModes.id;
            if (!IsCreateTree)
            {
                TreePickerControl.Height = Unit.Pixel(455);
            }
            else
            {
                TreePickerControl.Height = Unit.Pixel(298);
            }
            TreePickerControl.StartNodeID = StartNodeId;

            //Create the hidden field.
            PickedValue = new HiddenField();
            PickedValue.ID = "PickedValue";

            //Add the controls.
            this.Controls.Add(TreePickerControl);
            this.Controls.Add(PickedValue);

            if (!IsCreateTree)
            {
                //Create the message column.
                MessageColumn = new HtmlGenericControl("div");
                MessageColumn.ID = "MessageColumn";
                MessageColumn.Attributes.Add("class", "message propertypane");
                MessageColumn.InnerHtml =
                    "Only allowed media items that can be selected are displayed.<br/>" +
                    "Allowed extensions: " + DigibizMediaHelper.GetAllowedMessageExtensions(AllowedExtensions) + "<br/>" +
                    "Allowed Media Types: " + DigibizMediaHelper.GetAllowedMessageMediaTypes(AllowedMediaTypes);

                //Create the center column.
                CenterColumn = new HtmlGenericControl("div");
                CenterColumn.ID = "CenterColumn";
                CenterColumn.Attributes.Add("class", "center propertypane");

                PreviewColumn = new HtmlGenericControl("div");
                PreviewColumn.ID = "PreviewColumn";
                PreviewColumn.Attributes.Add("class", "preview propertypane");

                RightColumn = new HtmlGenericControl("div");
                RightColumn.ID = "RightColumn";
                RightColumn.Attributes.Add("class", "right propertypane");

                #region Search Controls
                if (SearchEnabled)
                {
                    SearchTextBox = new TextBox();
                    SearchTextBox.ID = "searchTextBox";
                    SearchTextBox.Attributes.Add("class", "searchtextbox");
                    SearchTextBox.Text = "Search media...";

                    SearchButton = new Button();
                    SearchButton.ID = "searchButton";
                    SearchButton.Text = "Search";
                    SearchButton.Attributes.Add("class", "searchbutton");

                    //add search controls to search container
                    CenterColumn.Controls.Add(SearchTextBox);
                    CenterColumn.Controls.Add(SearchButton);
                }
                #endregion

                //Add the controls.
                this.Controls.Add(MessageColumn);
                this.Controls.Add(CenterColumn);
                this.Controls.Add(RightColumn);
            }
            else
            {
                CreateColumn = new HtmlGenericControl("div");
                CreateColumn.ID = "CreateColumn";
                CreateColumn.Attributes.Add("class", "create propertypane");
                this.Controls.Add(CreateColumn);
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            TreePickerControl.NodeKey = "1000";

            SavePersistentValuesForTree();
        }

        /// <summary>
        /// Override render to control the exact output of what is rendered this includes instantiating the jquery plugin.
        /// </summary>
        /// <param name="writer"></param>
        protected override void Render(HtmlTextWriter writer)
        {
            writer.AddAttribute("class", PickerClass);
            writer.AddAttribute("id", this.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            writer.AddAttribute("class", "left propertypane");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            //Add the tree control.
            TreePickerControl.RenderControl(writer);
            writer.RenderEndTag();

            if (!IsCreateTree)
            {
                MessageColumn.RenderControl(writer);

                CenterColumn.RenderControl(writer);

                RightColumn.RenderControl(writer);
            }
            else
            {
                CreateColumn.RenderControl(writer);
            }

            //Render the hidden field.
            PickedValue.RenderControl(writer);

            writer.RenderEndTag();
            
            //Add jquery window load event to create the js tree picker.
            var jsMethod = string.Format("jQuery('#{0}').DigibizPicker('{1}', '{2}', '{3}', {4}, {5}, '{6}', '{7}', '{8}', '{9}', '{10}', '{11}', {12}, {13}, '{14}', '{15}');",
                TreePickerControl.ClientID,
                this.ClientID,
                IOHelper.ResolveUrl(SystemDirectories.Umbraco),
                "media",
                IsCreateTree.ToString().ToLower(),
                SelectStartNode.ToString().ToLower(),
                SelectMultipleNodes.ToString().ToLower(),
                AllowedExtensions,
                AllowedMediaTypes,
                DigibizConstants.NOACCESSID,
                CropPropertyAlias,
                CropName,
                SearchEnabled.ToString().ToLower(),
                AutoSuggestEnabled.ToString().ToLower(),
                SearchMethod,
                StartNodeId);
            var js = "jQuery(window).load(function() { " + jsMethod + " });";
                
            writer.WriteLine("<script type='text/javascript'>" + js + "</script>");

        }

        /// <summary>
        /// This will update the digibiz picker data which is used to store the start node.
        /// </summary>
        /// <remarks>
        /// This will save the data into a cookie and also into the request cookie. It must save
        /// it to both locations in case the request cookie has been changed and the request cookie
        /// is different than the response cookie. 
        /// </remarks>
        private void SavePersistentValuesForTree()
        {
            //Create the output cookie with all of the values of the request cookie.

            var newCookie = HttpContext.Current.Response.Cookies[DigibizConstants.COOKIENAME];
            if (newCookie == null && newCookie.Values.Count > 0)
            {
                newCookie = new HttpCookie(DigibizConstants.COOKIENAME);
            }

            //Store the start node id.
            newCookie.AddStartNodeIdForDataType(1000, StartNodeId);

            HttpContext.Current.Response.Cookies.Add(newCookie);

            //Add it to the request cookies too, thus overriding any old data.
            if (HttpContext.Current.Request.Cookies[DigibizConstants.COOKIENAME] != null && HttpContext.Current.Request.Cookies[DigibizConstants.COOKIENAME].Values.Count > 0)
            {
                //Remove the incoming one and replace with new one.
                HttpContext.Current.Request.Cookies.Remove(DigibizConstants.COOKIENAME);
            }

            HttpContext.Current.Request.Cookies.Add(newCookie);
        }
    }
}
